//
// Created by root on 19-8-4.
//

#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <jni.h>
#include <dlfcn.h>
#include "AndHook.h"
#include "hook_execve.h"
#include "log_utils.h"
#include "inject_compacter.h"
#include "process_utils.h"
#include "string_utils.h"
#include "jni_utils.h"
#include "sys_prop_utils.h"

#define TAG "ExeCVE"

bool should_block_spawn_root_shell(){
    if(getuid()!=0)
        return false;
    if(!is_sys_boot_completed()) {//系统启动完毕之前允许root打开shell
        LOGD("system have not been ready,root shell will be permitted\n");
        return false;
    }
    std::string operation=std::string("spawn root shell\n");
    int pid=getpid();
    std::string process_name_str=get_process_name(pid);
    operation.append("process:");operation.append(process_name_str);
    operation.append("(");operation.append(itoa(pid));operation.append(")");
    JNIEnv *env=get_jni_env();
    if(!env) {
        LOGE("it seems that process:%s(%d) is used to be an exploit\n",process_name_str.c_str(),pid);
        return true;
    }
    if(!post_auth_request(env,operation)){
        LOGE("user denies to let process:%s(%d) spawn a root shell\n",process_name_str.c_str(),pid);
        return true;
    }
    LOGD("user allows to let process:%s(%d) spawn a root shell\n",process_name_str.c_str(),pid);
    return false;
}

#define DEX2OAT_BIN "/system/bin/dex2oat"

typedef int (*func_execve)(const char* __file, char* const* __argv, char* const* __envp);
static func_execve old_execve= nullptr;

int my_execve(const char* __file, char* const* __argv, char* const* __envp){
    if(!old_execve){
        LOGE("fail to get old_execve\n");
        return JNI_ERR;
    }
    LOGD("before execve:%s",__file);
    if(strcmp(__file,DEX2OAT_BIN)==0){
        LOGE("attempt to block dex2oat\n");
        exit(0);
    }

    /*if(strstr(__file,"sh")!= nullptr && should_block_spawn_root_shell()){
        LOGE("attempt to block root shell\n");
        exit(0);
    }*/

    return old_execve(__file,__argv,__envp);
}

void hook_execve() {
    if(old_execve)
        return;
    void* execve_symbol=dlsym(RTLD_DEFAULT,"execve");//只有execve是系统调用，另外都是execve的封装
    AKHookFunction(execve_symbol,
            reinterpret_cast<void*>(my_execve), reinterpret_cast<void**>(&old_execve));
    LOGD("old_execve:%p\n",old_execve);
}
